/**
 * Copyright (c) 2019-2029, wwww.kiwipeach.cn (liuburu@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * https://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package cn.kiwipeach.blog.service.impl;

import cn.kiwipeach.blog.base.AjaxResponse;
import cn.kiwipeach.blog.database.domain.BlogCommentVO;
import cn.kiwipeach.blog.email.EmailBody;
import cn.kiwipeach.blog.enums.EmailContentType;
import cn.kiwipeach.blog.exception.BlogException;
import cn.kiwipeach.blog.database.generator.domain.CommentReply;
import cn.kiwipeach.blog.database.mapper.CustomBlogMapper;
import cn.kiwipeach.blog.database.mapper.CustomCommentReplyMapper;
import cn.kiwipeach.blog.param.CommentReplyParam;
import cn.kiwipeach.blog.service.ICommentReplyService;
import cn.kiwipeach.blog.service.IEmailService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import open.kiwipeach.autoconfigure.shiro.token.AccessToken;
import open.kiwipeach.autoconfigure.web.utils.UserUtil;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;

/**
 * 评论 服务实现类
 *
 * @author kiwipeach
 * @since 1.0
 */
@Service
public class CommentReplyServiceImpl extends ServiceImpl<CustomCommentReplyMapper, CommentReply> implements ICommentReplyService {

    @Autowired
    private CustomBlogMapper customBlogMapper;

    @Autowired
    private CustomCommentReplyMapper customCommentReplyMapper;

    @Autowired
    org.springframework.cache.CacheManager cacheManager;

    @Autowired
    private IEmailService iEmailService;

    @Value("${blog.shiro.cookie.domain}")
    private String website;


    @Override
    public AjaxResponse<BlogCommentVO> createBlogComment(CommentReplyParam commentReply, AccessToken accessToken) {
        // 入参信息校验
        if (StringUtils.isEmpty(commentReply.getContent())) {
            throw new BlogException("-COMMENT-002", "博客评论内容不能为空");
        }
        // 0) 查找当前登录用户信息
        AccessToken currentUser = UserUtil.getCurrentUser();
        commentReply.setActiveUserId(currentUser.getId());
        // 1) 插入评论内容
        commentReply.setType("B_BLOG_COMMENT");
        if (customCommentReplyMapper.insert(commentReply) == 0) {
            throw new BlogException("-COMMENT-002", "博客评论插入失败！");
        }
        // 2）更新博客统计字段
        if (updateBlogCommentCount(commentReply.getParentId()) == false) {
            throw new BlogException("-COMMENT-002", "博客评论统计更新失败！");
        }
        // 3) 邮件通知站长
        //notifyWebsiteMaster(commentReply.getContent(), commentReply.getBlogId(), "http://www.kiwipeach.cn/");
        return AjaxResponse.success(customCommentReplyMapper.selectCommenReplyById(commentReply.getId()));
    }

    @Override
    public AjaxResponse<BlogCommentVO> createCommentReply(CommentReplyParam commentReply, AccessToken accessToken) {
        //信息校验
        if (StringUtils.isEmpty(commentReply.getContent())) {
            throw new BlogException("-COMMENT-002", "博客回复内容不能为空");
        }
        // 0) 查找当前登录用户信息
        AccessToken currentUser = UserUtil.getCurrentUser();
        commentReply.setActiveUserId(currentUser.getId());
        // 1)插入回复内容
        commentReply.setType("B_COMMENT_REPLY");
        if (customCommentReplyMapper.insert(commentReply) == 0) {
            throw new BlogException("-COMMENT-002", "评论回复内容插入失败！");
        }
        // 2)维护博客评论回复统计字段
        if (updateBlogCommentCount(commentReply.getBlogId()) == false) {
            throw new BlogException("-COMMENT-002", "博客评论统计更新失败！");
        }
        // 3)维护评论回复统计字段
        CommentReply curCommentReply = customCommentReplyMapper.selectById(commentReply.getParentId());
        int count = Integer.parseInt(curCommentReply.getReplyCount()) + 1;
        curCommentReply.setReplyCount(String.valueOf(count));
        if (customCommentReplyMapper.updateById(curCommentReply) == 0) {
            throw new BlogException("-COMMENT-002", "博客评论回复统计失败！");
        }
        // 4) FIXME 邮件通知站长(可以做成异步)
        //notifyWebsiteMaster(commentReply.getContent(), commentReply.getBlogId(), "http://www.kiwipeach.cn/");
        return AjaxResponse.success(customCommentReplyMapper.selectCommenReplyById(commentReply.getId()));
    }

    /**
     * 将评论和回复邮件通知给站长
     *
     * @param content 邮件内容
     */
    private void notifyWebsiteMaster(String content, String blogId, String website) {
        //开启一个线程专门发送邮件内容
        //org.apache.commons.lang3.concurrent.BasicThreadFactory
        ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
                new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                AccessToken currentUser = UserUtil.getCurrentUser();
                Set<String> paramSet = new LinkedHashSet<>();
                paramSet.add(currentUser.getNickName());
                //例如：http://www.kiwipeach.cn/blog/detail/103
                paramSet.add(new StringBuffer(website).append("blog/detail/").append(blogId).toString());
                paramSet.add(content);
                paramSet.add(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date()));
                EmailBody emailBody = new EmailBody(Arrays.asList("liuburu@qq.com"), "Nice Blog Sys 新的评论回复通知", paramSet);
                //如果是模板邮件，一定不要忘记执行这句代码
                emailBody.setEmailContentType(EmailContentType.MESSAGE_FORMAT_OF_BLOG_COMMENT_REPLY);
                iEmailService.sendEmail(emailBody);
            }
        });
    }

    /**
     * 抖音评论回复排序权重： 关注 > 点赞 > 时间 > 回复（默认评论会显示：关注对象，点赞超过1000的的对象，刚刚发表评论的对象）
     * nice blog的回复排序： 点赞 > 回复 > 时间
     *
     * @param page     分页入参
     * @param parentId 博客编号
     * @param type     查询类型 B_COMMENT,B_COMMENT_REPLY,B_REPLY_REPLY,L_COMMENT,L_COMMENT_REPLY,L_REPLY_REPLY
     * @return
     */
    @Override
    public AjaxResponse<IPage<BlogCommentVO>> queryCommentByPage(IPage<BlogCommentVO> page, String parentId, String type) {
        List<BlogCommentVO> blogCommentVOS = customCommentReplyMapper.selectCommenByPage(page, parentId, Arrays.asList(type));
        // 如果是博客回复或者留言留言，那么就需要去加载留言对应的分页回复消息
        // B_COMMENT,B_COMMENT_REPLY,B_REPLY_REPLY,L_COMMENT,L_COMMENT_REPLY,L_REPLY_REPLY
        if ("B_BLOG_COMMENT".equals(type)) {
            // 评论加载回复
            IPage<BlogCommentVO> commentReplyPage = new Page<>();
            commentReplyPage.setSize(3).setCurrent(1);
            for (BlogCommentVO commentVO : blogCommentVOS) {
                List<BlogCommentVO> commentReplies = customCommentReplyMapper.selectCommenByPage(commentReplyPage, commentVO.getId(), Arrays.asList("B_COMMENT_REPLY", "B_REPLY_REPLY"));
                commentVO.setCommentReplies(commentReplies);
            }
        } else if ("L_COMMENT_TYPE".equals(type)) {
            IPage<BlogCommentVO> commentReplyPage = new Page<>();
            commentReplyPage.setSize(3).setCurrent(1);
            // 留言加载回复
            for (BlogCommentVO commentVO : blogCommentVOS) {
                List<BlogCommentVO> commentReplies = customCommentReplyMapper.selectCommenByPage(commentReplyPage, commentVO.getId(), Arrays.asList("L_COMMENT_REPLY", "L_REPLY_REPLY"));
                commentVO.setCommentReplies(commentReplies);
            }
        }
        page.setRecords(blogCommentVOS);
        return AjaxResponse.success(page);
    }

    @Override
    public AjaxResponse<Boolean> modifyCommentReplyStarCount(String commentId, String sessionid) {
        //如果缓存中存在点赞数据，则不允许重复点赞
        String cacheKey = String.format("commentid_%s_sessionid_%s", commentId, sessionid);
        Cache commentReplyCountCache = cacheManager.getCache("BLOG_COMMENT_REPLY_COUNT");
        Cache.ValueWrapper valueWrapper = commentReplyCountCache.get(cacheKey);
        if (valueWrapper == null) {
            Integer integer = customCommentReplyMapper.updateCommentStarCount(commentId);
            if (integer > 0) {
                commentReplyCountCache.put(cacheKey, integer);
                return AjaxResponse.success(true);
            } else {
                return AjaxResponse.fail("-BLOG_STAR_001", "评论点赞失败");
            }
        } else {
            return AjaxResponse.fail("-BLOG_STAR_001", "该评论您期点过赞");
        }
    }


    /**
     * 更新博客统计字段
     *
     * @param blogId 博客编号
     * @return 返回更新成功
     */
    private boolean updateBlogCommentCount(String blogId) {
        return customBlogMapper.updateCommentCountByBlogId(blogId) > 0 ? true : false;
    }

    /**
     * 更新博客回复统计字段
     *
     * @param commentReply
     * @return 返回更新成功
     */
    private boolean updateCommentReplyCount(CommentReply commentReply) {
        commentReply.setReplyCount(commentReply.getReplyCount() + 1);
        return customCommentReplyMapper.updateById(commentReply) > 0 ? true : false;
    }


}
